package com.code.origin.utils.log;

import cn.hutool.core.util.ObjectUtil;
import com.code.origin.utils.string.StringUtils;
import com.code.origin.utils.datetime.DateUtils;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

public class LogFormatUtils {
	
	public final static String INFO = "[信息]";
	
	public final static String ERROR = "[错误]";
	
	/**
	 * 通用打印信息
	 * <pre>mainInfos：string参数内容即可，不用加[]，建议不少于2个，第一个为业务说明如：饿百拉取信息，第二个为描述内容，如：违反唯一约束</pre>
	 * <pre>objectParams：类的所有属性以及内容，最终格式为：[<属性名1>内容1][<属性名2>内容2]...</pre>
	 */
	public static String infoFormatObject(Object objectParams, String... mainInfos) {
		
		return formatCommonObject(INFO, objectParams, mainInfos);
	}
	
	/**
	 * 通用打印信息
	 * <pre>mainInfos：string参数内容即可，不用加[]，建议不少于2个，第一个为业务说明如：饿百拉取信息，第二个为描述内容，如：违反唯一约束</pre>
	 * <pre>objectParams：类的所有属性以及内容，最终格式为：[<属性名1>内容1][<属性名2>内容2]...</pre>
	 */
	public static String errorFormatObject(Object objectParams, String... mainInfos) {
		
		return formatCommonObject(ERROR, objectParams, mainInfos);
	}
	
	/**
	 * 通用打印信息
	 * <pre>mainInfos：string参数内容即可，不用加[]，建议不少于2个，第一个为业务说明如：饿百拉取信息，第二个为描述内容，如：违反唯一约束</pre>
	 * <pre>objectParams：类的所有属性以及内容，最终格式为：[<属性名1>内容1][<属性名2>内容2]...</pre>
	 * <pre>type：类型，目前主要有[信息][错误]</pre>
	 */
	public static String formatCommonObject(String type, Object objectParams, String... mainInfos) {
		StringBuffer sb = new StringBuffer();
		if (StringUtils.isNotEmpty(type)) {
			sb.append(type);
		}
		if (ObjectUtil.isNotNull(mainInfos)) {
			sb.append(formatParamsString(mainInfos));
		}
		if (ObjectUtil.isNotNull(objectParams)) {
			sb.append(formatParamsObject(objectParams));
		}
		return appendTime(sb.toString());
	}
	
	
	/**
	 * 打印信息逐个追加Object参数
	 */
	public static String formatParamsObject(Object object) {
		StringBuffer sb = new StringBuffer();
		Class<?> clazz = object.getClass();
		Field[] fields = null;
		for(; clazz != Object.class; clazz = clazz.getSuperclass()) {
			fields = clazz.getDeclaredFields();
			for (Field field : fields) {
				try {
					String fieldName = field.getName();
					//过滤掉这个，因为如果传的是entity时，没有get、set方法
					if (!"serialVersionUID".equals(fieldName)) {
						sb.append("[<");
						sb.append(fieldName);
						sb.append(">");
						if (!Modifier.isPublic(field.getModifiers())) {
							String getMethod = toUpperCaseFirstChar(fieldName);
							if (getMethod != null) {
								Method m;
								try {
									m = clazz.getMethod(getMethod, null);
									sb.append(m.invoke(object, null));
								} catch (NoSuchMethodException | SecurityException e) {
									//不处理，没有就没有，自己根据日志检查吧，因为如果是entity，那么serialVersionUID铁定没有哒~
								}
							}
						} else {
							sb.append(field.get(fieldName));
						}
						sb.append("]");
					}
					
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				} catch (InvocationTargetException e) {
					
				}
			}
		}
		
		return sb.toString();
	}
	
	
	public static String toUpperCaseFirstChar(String fieldName) {
		if (fieldName != null && !fieldName.isEmpty()) {
			String res = null;
			if (fieldName.length() > 1) {
				res = "get" + (fieldName.substring(0,1)).toUpperCase() + fieldName.substring(1);
			} else {
				res = "get" + fieldName.toUpperCase();
			}
			return res;
		} else {
			return null;
		}
	}
	
	/**
	 * 通用[信息]类打印信息
	 * <pre>mainInfo：[区分信息][说明]...</pre>
	 * <pre>params：string参数内容即可，不用加[]</pre>
	 */
	public static String infoFormatString(String mainInfo, String... params) {
		
		return formatCommonString(mainInfo, INFO, params);
	}
	
	/**
	 * 通用[错误]类打印信息
	 * <pre>mainInfo：[区分信息][说明]...</pre>
	 * <pre>params：string参数内容即可，不用加[]</pre>
	 */
	public static String errorFormatString(String mainInfo, String... params) {
		
		return formatCommonString(mainInfo, ERROR, params);
	}
	
	/**
	 * 通用打印信息
	 */
	public static String formatCommonString(String mainInfo,String type, String... params) {
		String res = mainInfo + type + formatParamsString(params);
		return appendTime(res);
	}
	
	/**
	 * 打印信息逐个追加String参数
	 */
	public static String formatParamsString(String... params) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < params.length; i++) {
			sb.append("[");
			sb.append(params[i]);
			sb.append("]");
		}
		return sb.toString();
	}

	/**
	 * 打印信息追加日期
	 */
	public static String appendTime(String info) {
		return info + "[" + DateUtils.now() + "]";
	}
}
